﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using DG.Tweening;
using UnityEngine.UI;

public class GameplayControl : MonoBehaviour
{
	public static GameplayControl instance;
	public GameObject board, miniBoard;
	public List<Block> listAllBlock;
	Cell[,] Cells = new Cell[6, 6];
	Dictionary<string,string> stageInfo;
	public bool isMoving = false, isWaitingMove = false, isAutoMove = false;
	public List<Block> listBlockMoveH, listBlockMoveV, listBlockMove;
	MoveDir moveDir;
	public bool canClickMove = true;
	public List<UndoModule> listUndo;
	UndoModule hintUndo;
	int _moveCount;
	bool lastStepIsMove = false;
	public SpriteRenderer hintDot;
	public Image iStageClear;

	public Button bUndo, bReplay, bHint;
	public Image iTutorial;

	public int moveCount {
		get { return _moveCount; }
		set {
			_moveCount = value;

			GameplayUI.instance.tMove.text = value.ToString ();

		}
	}

	void Awake ()
	{
		listUndo = new List<UndoModule> ();
		Cells = new Cell[6, 6];
		LoadStageInfo ();
		instance = this;
	}

	void CreateBoard (GameObject prefap, GameObject parrent, int col, int row, float cellWidth, float cellHeight)
	{
		for (int x = 0; x < row; x++) {
			for (int y = 0; y < col; y++) {
				GameObject cellObj = (GameObject)Instantiate (prefap, new Vector3 (parrent.transform.position.x - (float)col / 2 + cellWidth / 2 + x * cellWidth, parrent.transform.position.x - (float)row / 2 + cellHeight / 2 + y * cellHeight, 0), Quaternion.identity);
			}
		}
	}

	void LoadStageInfo ()
	{
		TextAsset ta = Resources.Load ("stageInfo") as TextAsset;
		stageInfo = JsonConvert.DeserializeObject<Dictionary<string,string>> (ta.text);
	}

	StageModule LoadStageData (int level)
	{
		string path = "data/" + stageInfo ["stage" + level];

		path = path.Replace (".json", "");
		Debug.Log ("Path la : " + path);
		TextAsset ta = Resources.Load<TextAsset> (path) as TextAsset;
		Debug.Log ("Text la : " + ta.text);
		StageModule md = JsonUtility.FromJson<StageModule> (ta.text);
		return md;
	}

	void OnEnable ()
	{
		iStageClear.gameObject.SetActive (false);
		if (inited == true) {
			StartNewGame ();
		}
	}

	bool inited = false;

	void Start ()
	{
		iTutorial.gameObject.SetActive (false);
		bHint.image.color = new Color (1, 1, 1, 0.5F);
		bUndo.image.color = new Color (1, 1, 1, 0.5F);
		tempPos = new Vector3 (0, 0, 0);
		listBlockMoveH = new List<Block> ();
		listBlockMoveV = new List<Block> ();
		listBlockMove = new List<Block> ();
		listAllBlock = new List<Block> ();

		//CreateBoard (GameDefine.instance.cellPrefap, board, 6, 6, 1, 1);
		//CreateBoard (GameDefine.instance.blockPrefap, board, 8, 8, 1, 1);
		// create cell 
		int col = 6, row = 6;
		float cellWidth = 0.3F, cellHeight = 0.3F;
		for (int x = 0; x < col; x++) {
			for (int y = 0; y < row; y++) {
				GameObject cellObj = (GameObject)Instantiate (GameDefine.instance.cellPrefap, new Vector3 (miniBoard.transform.position.x - (float)col * cellWidth / 2 + cellWidth / 2 + x * cellWidth, miniBoard.transform.position.y + (float)row * cellHeight / 2 - cellHeight / 2 - y * cellHeight, 0), Quaternion.identity);
				Cell cell = cellObj.GetComponent<Cell> ();
				Cells [x, y] = cell;
				cellObj.transform.SetParent (miniBoard.transform);
				cellObj.name = "Cell_" + x + "_" + y;
			}
		}
		// create block
		col = 18;
		row = 18;
		cellWidth = 1;
		cellHeight = 1;
		for (int x = 0; x < col; x++) {
			for (int y = 0; y < row; y++) {
				GameObject blockObj = (GameObject)Instantiate (GameDefine.instance.blockPrefap, new Vector3 (board.transform.position.x - (float)col / 2 + cellWidth / 2 + x * cellWidth, board.transform.position.y + (float)row / 2 - cellHeight / 2 - y * cellHeight, 0), Quaternion.identity);
				Block bl = blockObj.GetComponent<Block> ();
				bl.id = row * y + x;
				bl.x = x;
				bl.y = y;
				bl.colorId = 0;
				listAllBlock.Add (bl);
				blockObj.transform.SetParent (board.transform);
				blockObj.name = "Block_" + x + "_" + y;

			}
		}
		StartNewGame ();
		inited = true;
	}



	StageModule md;

	public void StartNewGame ()
	{
//		if (Admob.instance.isVideoAdmobLoad ()) {
//			bHint.image.color = new Color (1, 1, 1, 1);
//		} else {
//			bHint.image.color = new Color (1, 1, 1, 0.5F);
//			Admob.instance.ReloadVideoAds ();
//		}
		hintCount = 0;
		hintDot.transform.position = new Vector3 (20, 20, 0);
		hintUndo = null;
		lastStepIsMove = false;
		moveCount = 0;
		GameplayUI.instance.tStage.text = GameManager.currentLevel.ToString ();
		listUndo.Clear ();
		listBlockMoveH.Clear ();
		listBlockMoveV.Clear ();
		listBlockMove.Clear ();
		// tao bang 
		md = LoadStageData (GameManager.currentLevel);
		Debug.Log ("Start level " + GameManager.currentLevel + " data  : " + md);
		// set cellColorID
		for (int i = 0; i < md.solution.Count; i++) {
			int y = i / 6;
			int x = i % 6;
			Cells [x, y].colorID = md.solution [i] == 1 ? md.color1 : md.color2;
		}
		// set block ColorID;
		for (int i = 0; i < md.start.Count; i++) {
			int y = i / 6;
			int x = i % 6;
			for (int j = 0; j < listAllBlock.Count; j++) {
				Block bl = listAllBlock [j];
				if ((bl.x == x && bl.y == y) || (bl.x == x && bl.y == y + 6) || (bl.x == x && bl.y == y + 12)) {
					bl.colorId = md.start [i] == 1 ? md.color1 : md.color2;
				}
				if ((bl.x == x + 6 && bl.y == y) || (bl.x == x + 6 && bl.y == y + 6) || (bl.x == x + 6 && bl.y == y + 12)) {
					bl.colorId = md.start [i] == 1 ? md.color1 : md.color2;
				}
				if ((bl.x == x + 12 && bl.y == y) || (bl.x == x + 12 && bl.y == y + 6) || (bl.x == x + 12 && bl.y == y + 12)) {
					bl.colorId = md.start [i] == 1 ? md.color1 : md.color2;
				}
			}
		}

		/*
		for (int i = 0; i < listAllBlock.Count; i++) {
			Block bl = listAllBlock [i];

			for (int j = 0; j < listAllBlock.Count; j++) {
				Block bl2 = listAllBlock [j];
				if (bl.x == 1 && bl.y == bl2.y && bl2.x == 7) {
					bl2.colorId = bl.colorId;
				}
				if (bl.y == 1 && bl.x == bl2.x && bl2.y == 7) {
					bl2.colorId = bl.colorId;
				}
				if (bl.x == 6 && bl.y == bl2.y && bl2.x == 0) {
					bl2.colorId = bl.colorId;
				}
				if (bl.y == 6 && bl.x == bl2.x && bl2.y == 0) {
					bl2.colorId = bl.colorId;
				}
			}
		}
		*/

		GameManager.gameState = GameState.PLAYING;
		if (GameManager.currentLevel == 1) {
			ShowTutorialImage ();
		}

	}

	public void ShowTutorialImage ()
	{
		iTutorial.gameObject.SetActive (true);
	}

	public void CloseTutorialImage ()
	{
		iTutorial.gameObject.SetActive (false);
	}

	void Update ()
	{
		
		mousePos = Camera.main.ScreenToWorldPoint (Input.mousePosition);
	}

	void LateUpdate ()
	{
		Move ();
	}

	Vector3 initMovePos;

	public void InitMove (Block block)
	{
		if (lastStepIsMove == false) {
			CreateUndo ();
		}
		checkWin = false;
		listBlockMoveH.Clear ();
		listBlockMoveV.Clear ();
		listBlockMove.Clear ();
		for (int i = 0; i < listAllBlock.Count; i++) {
			Block bl = listAllBlock [i];
			if (bl.x == block.x) {
				listBlockMoveV.Add (bl);
			}
			if (bl.y == block.y) {
				listBlockMoveH.Add (bl);
			}
		}
		initMovePos = Camera.main.ScreenToWorldPoint (Input.mousePosition);
		isWaitingMove = true;
	}

	Vector3 startMoveMousePos;
	Vector3 tempPos;
	Vector3 mousePos;
	Vector3 mpTemp;
	// kiem tra xem da checkwin chua
	bool checkWin = false;

	void Move ()
	{
		
		if (isWaitingMove == true) {			
			mpTemp = mousePos;
			float a = Mathf.Abs (mousePos.x - initMovePos.x);
			float b = Mathf.Abs (mousePos.y - initMovePos.y);
			if (a > 0 && a > b) {
				moveDir = MoveDir.H;
				listBlockMove = listBlockMoveH;
				isWaitingMove = false;
				isMoving = true;
			}
			if (b > 0 && b > a) {
				moveDir = MoveDir.V;
				isWaitingMove = false;
				listBlockMove = listBlockMoveV;
				isMoving = true;
			}
			// init pos 
			for (int i = 0; i < listBlockMove.Count; i++) {
				Block bl = listBlockMove [i];
				bl.offset = bl.transform.position - mousePos;
			}
		}
		bool haveChange = false;
		if (isMoving == true) {
			for (int i = 0; i < listBlockMove.Count; i++) {
				Block bl = listBlockMove [i];
				if (moveDir == MoveDir.H) {
					tempPos.x = mousePos.x + bl.offset.x;
					tempPos.y = bl.transform.position.y;
					bl.transform.position = tempPos;

					if (tempPos.x > 9.5F) {
						
						tempPos.x = tempPos.x - 18;
						bl.transform.position = tempPos;
						bl.offset = bl.transform.position - mousePos;
						listBlockMove.Sort (((x, y) => x.transform.position.x.CompareTo (y.transform.position.x)));
						UpdateBlockXY (listBlockMove, true);
						haveChange = true;

					}
					if (tempPos.x < -9.5F) {
						tempPos.x = tempPos.x + 18;
						bl.transform.position = tempPos;
						bl.offset = bl.transform.position - mousePos;
						listBlockMove.Sort (((x, y) => x.transform.position.x.CompareTo (y.transform.position.x)));
						//bl.colorId = listBlockMove [1].colorId;
						UpdateBlockXY (listBlockMove, true);
						haveChange = true;
					}

				} else {
					tempPos.x = bl.transform.position.x;
					tempPos.y = mousePos.y + bl.offset.y;
					bl.transform.position = tempPos;

					if (tempPos.y > 9.5F + board.transform.position.y) {
						//Debug.Log ("Tempos la : " + tempPos);
						//Debug.Log (board.transform.position.y);
						tempPos.y = tempPos.y - 18;
						bl.transform.position = tempPos;
						bl.offset = bl.transform.position - mousePos;
						listBlockMove.Sort (((x, y) => x.transform.position.y.CompareTo (y.transform.position.y)));
						//bl.colorId = listBlockMove [listBlockMove.Count - 2].colorId;
						UpdateBlockXY (listBlockMove, false);
						haveChange = true;
					}
					if (tempPos.y < -9.5F + board.transform.position.y) {
						tempPos.y = tempPos.y + 18;
						bl.transform.position = tempPos;
						bl.offset = bl.transform.position - mousePos;
						listBlockMove.Sort (((x, y) => x.transform.position.y.CompareTo (y.transform.position.y)));
						//bl.colorId = listBlockMove [1].colorId;
						UpdateBlockXY (listBlockMove, false);
						haveChange = true;
					}


				}

			}



			if (Input.GetMouseButtonUp (0)) {
				
				isMoving = false;



				if (moveDir == MoveDir.V) {
					listBlockMove.Sort (((x, y) => x.transform.position.y.CompareTo (y.transform.position.y)));	
				} else {
					listBlockMove.Sort (((x, y) => x.transform.position.x.CompareTo (y.transform.position.x)));	
				}
				UpdateBlockXY (listBlockMove, moveDir == MoveDir.H ? true : false);
				int col = 18;
				int row = 18;
				float cellWidth = 1;
				float cellHeight = 1;
				for (int i = 0; i < listBlockMove.Count; i++) {
					Block bl = listBlockMove [i];
					Vector3 pos = new Vector3 (board.transform.position.x - (float)col / 2 + cellWidth / 2 + bl.x * cellWidth, board.transform.position.y + (float)row / 2 - cellHeight / 2 - bl.y * cellHeight, 0);
					if (moveDir == MoveDir.H) {
						if (bl.transform.position.x - pos.x > cellWidth / 2) {
							pos.x = pos.x + cellWidth;
							if (i == listBlockMove.Count - 1) {
								Vector3 posTemp = bl.transform.position;
								posTemp.x -= 18;
								bl.transform.position = posTemp;
								pos.x = pos.x - 18;
								bl.offset = bl.transform.position - mousePos;
								//listBlockMove.Sort (((x, y) => x.transform.position.x.CompareTo (y.transform.position.x)));
								//UpdateBlockXY (listBlockMove, true);
							}
						} else if (-bl.transform.position.x + pos.x > cellWidth / 2) {
							pos.x = pos.x - cellWidth;
							if (i == 0) {
								Vector3 posTemp = bl.transform.position;
								posTemp.x += 18;
								bl.transform.position = posTemp;
								pos.x = pos.x + 18;
								bl.offset = bl.transform.position - mousePos;
								//listBlockMove.Sort (((x, y) => x.transform.position.x.CompareTo (y.transform.position.x)));
								//UpdateBlockXY (listBlockMove, true);
							}
						}
					} else {
						//Debug.Log ("aaaaa " + (bl.transform.position.y - pos.y) + "   CellHeight : " + cellHeight / 2 + " dich len la : " + ((bl.transform.position.y - pos.y > cellHeight / 2) ? "true" : "false"));
						if (bl.transform.position.y - pos.y > cellHeight / 2) {
							
							pos.y = pos.y + cellHeight;

							if (i == listBlockMove.Count - 1) {
								Vector3 posTemp = bl.transform.position;
								posTemp.y -= 18;
								bl.transform.position = posTemp;
								pos.y = pos.y - 18;
								bl.offset = bl.transform.position - mousePos;
								//listBlockMove.Sort (((x, y) => x.transform.position.y.CompareTo (y.transform.position.y)));
								//UpdateBlockXY (listBlockMove, false);
							}

						} else if (-bl.transform.position.y + pos.y > cellHeight / 2) {

							pos.y = pos.y - cellHeight;

							if (i == 0) {
								Vector3 posTemp = bl.transform.position;
								posTemp.y += 18;
								bl.transform.position = posTemp;
								pos.y = pos.y + 18;
								bl.offset = bl.transform.position - mousePos;
								//listBlockMove.Sort (((x, y) => x.transform.position.y.CompareTo (y.transform.position.y)));
								//UpdateBlockXY (listBlockMove, false);
							}

						}
					}
					bl.transform.DOMove (pos, 0.2F).SetEase (Ease.OutBack).OnComplete (() => {
						if (checkWin == false) {
							checkWin = true;
							Invoke ("CheckWin", 0.2F);
							//CheckWin ();
						}
					});
				}
				//////
				for (int j = 0; j < listBlockMove.Count; j++) {
					Block bl = listBlockMove [j];
					for (int i = 0; i < listAllBlock.Count; i++) {
						Block blCheck = listAllBlock [i];
						if (moveDir == MoveDir.H) {
							if (blCheck.x == bl.x && (blCheck.y == bl.y - 6 || blCheck.y == bl.y + 6)) {
								blCheck.colorId = bl.colorId;
							}
						}
						if (moveDir == MoveDir.V) {
							if (blCheck.y == bl.y && (blCheck.x == bl.x - 6 || blCheck.x == bl.x + 6)) {
								blCheck.colorId = bl.colorId;
							}
						}
					}
				}

				// 
				Vector3 releaseMousePos = Camera.main.ScreenToWorldPoint (Input.mousePosition);
				if (Vector3.Distance (releaseMousePos, initMovePos) >= 0.5F) {
					moveCount++;
					lastStepIsMove = true;
					CreateUndo ();
				}

			}

		}

		if (haveChange) {
			Debug.Log ("HaveChange");
			AudioManager.instance.PlaySound (AudioClipType.SE_Move);
		}
	}

	void CheckWin ()
	{
		if (moveDir == MoveDir.H) {
			listBlockMove.Sort (((x, y) => x.transform.position.x.CompareTo (y.transform.position.x)));
			UpdateBlockXY (listBlockMove, true);
		} else {
			listBlockMove.Sort (((x, y) => x.transform.position.y.CompareTo (y.transform.position.y)));
			UpdateBlockXY (listBlockMove, false);
		}
		//----------------- tinh toan hint 
		if (isHinting == true) {
			float distance = Vector3.Distance (startBlock.transform.position, endBlockPos);
			Debug.Log ("Distance = " + distance);
			if (distance <= 0.1F) {						
				numHint++;
				CreateHintUndo ();
				hintCount++;
			} else {
				// dat lai color nhu luc ban dau
				if (hintUndo != null) {
					for (int i = 0; i < listAllBlock.Count; i++) {
						Block bl = listAllBlock [i];
						bl.colorId = hintUndo.Values [bl.x, bl.y];
					}
				} else {
					UndoModule undoStart = listUndo [0];
					for (int i = 0; i < listAllBlock.Count; i++) {
						Block bl = listAllBlock [i];
						bl.colorId = undoStart.Values [bl.x, bl.y];
					}
				}
				startBlock = GetBlock ((int)startBlockXY.x, (int)startBlockXY.y);
				endBlock = GetBlock ((int)endBlockXY.x, (int)endBlockXY.y);
			}
		}
		bool isWin = true;
		for (int i = 0; i < listAllBlock.Count; i++) {
			Block bl = listAllBlock [i];
			if (bl.x >= 6 && bl.y >= 6 && bl.x < 12 && bl.y < 12) {
				//Debug.Log ("Cell " + (bl.x - 6) + ":" + (bl.y - 6) + " co color la ; " + Cells [bl.x - 6, bl.y - 6].colorID + " and bl " + bl.x + ":" + bl.y + " co color la : " + bl.colorId);
				if (Cells [bl.x - 6, bl.y - 6].colorID != bl.colorId) {
					isWin = false;
					break;
				}
			}
		}

		if (isWin == true) {
			Debug.Log ("Chien Thang");
			GameManager.gameState = GameState.WIN;
			iStageClear.transform.localScale = new Vector3 (1, 0, 1);
			AudioManager.instance.PlayMusic (AudioClipType.SE_Clear);
			iStageClear.gameObject.SetActive (true);
			iStageClear.transform.DOScaleY (1, 1F).SetEase (Ease.OutBack).OnComplete (() => {
				Invoke ("ShowWinPopup", 1.5F);
			});

		}
		canClickMove = true;
		// add to undo 

	}

	void ShowWinPopup ()
	{
		iStageClear.gameObject.SetActive (false);
		AudioManager.instance.PlayMusic (AudioClipType.BGM_Result);
		GameplayUI.instance.popupWin.gameObject.SetActive (true);
		//Admob.instance.ShowIads ();
		//AdsControl.Instance.ShowInterstitial();
	}

	void UpdateBlockXY (List<Block> list, bool isUpdateX)
	{
		
		for (int i = 0; i < list.Count; i++) {
			if (isUpdateX) {
				list [i].x = i;
			} else {
				list [i].y = 17 - i;
			}
		}

	}

	Block GetBlock (int x, int y)
	{
		for (int i = 0; i < listAllBlock.Count; i++) {
			Block bl = listAllBlock [i];
			if (bl.x == x && bl.y == y) {
				return bl;
			}
		}
		return null;
	}

	float GetFirstPos (List<Block> list, MoveDir mvDir, bool isGetMin)
	{
		float min = 1000;
		float max = -1000;
		for (int i = 0; i < list.Count; i++) {
			Block bl = list [i];
			if (mvDir == MoveDir.H) {
				if (bl.transform.position.x < min) {
					min = bl.transform.position.x;
				}
				if (bl.transform.position.x > max) {
					max = bl.transform.position.x;
				}
			}
			if (mvDir == MoveDir.V) {
				if (bl.transform.position.y < min) {
					min = bl.transform.position.y;
				}
				if (bl.transform.position.y > max) {
					max = bl.transform.position.y;
				}
			}
		}
		return isGetMin ? min - 1 : max + 1;
	}

	void OnEndMove ()
	{
		canClickMove = true;
	}

	///------------------------------------ UI ------------------------------
	public void Replay ()
	{
		AudioManager.instance.PlaySound (AudioClipType.SE_Enter);
		StartNewGame ();
		//Admob.instance.ShowIads ();
	}

	void CreateUndo ()
	{
		UndoModule undo = new UndoModule ();
		listUndo.Add (undo);
		for (int i = 0; i < listAllBlock.Count; i++) {
			Block bl = listAllBlock [i];
			undo.Values [bl.x, bl.y] = bl.colorId;
		}
		if (bUndo.image.color.a < 1) {
			bUndo.image.color = new Color (1, 1, 1, 1);
		}
	}

	public void Undo ()
	{
		if (GameManager.gameState != GameState.PLAYING) {
			return;
		}
		AudioManager.instance.PlaySound (AudioClipType.SE_Enter);
		Debug.Log ("ListUndoCount : " + listUndo.Count);
		if (lastStepIsMove) {
			listUndo.RemoveAt (listUndo.Count - 1);
		}
		if (listUndo.Count > 0) {
			Debug.Log ("Undo");
			UndoModule undo = listUndo [listUndo.Count - 1];
			for (int i = 0; i < listAllBlock.Count; i++) {
				Block bl = listAllBlock [i];
				bl.colorId = undo.Values [bl.x, bl.y];
			}
			listUndo.Remove (undo);
			lastStepIsMove = false;
			if (listUndo.Count == 0) {
				bUndo.image.color = new Color (1, 1, 1, 0.5F);
			}
		} else {
			
			bUndo.image.color = new Color (1, 1, 1, 0.5F);				
		}
	}

	int hintCount = 0;

	public void RequestHintAd ()
	{
		if (GameManager.gameState != GameState.PLAYING) {
			return;
		}
//		if (bHint.image.color.a < 1) {
//			Admob.instance.ReloadVideoAds ();
//
//		} else {
//			if (Admob.instance.isVideoAdmobLoad () == true) {
//				Admob.instance.ShowRewardedAd (VideoAdsRewardType.AD_REWARD_HINT);
//				bHint.image.color = new Color (1, 1, 1, 0.5F);
//			} else {
//				bHint.image.color = new Color (1, 1, 1, 0.5F);
//				Admob.instance.ReloadVideoAds ();
//			}
//		}
	}

	public void Hint ()
	{
		
		AudioManager.instance.PlaySound (AudioClipType.SE_Enter);
		if (hintUndo != null) {
			Debug.Log ("Undo last hint ");
			for (int i = 0; i < listAllBlock.Count; i++) {
				Block bl = listAllBlock [i];
				bl.colorId = hintUndo.Values [bl.x, bl.y];
			}
			listUndo.Clear ();
		} else {
			Debug.Log ("Undo startGame ");
			if (moveCount > 0) {
				StartNewGame ();
			}
		}

		if (hintCount < md.steps.Count) {
			StartCoroutine (HintCoroutine (hintCount));

		}

	}
	//----------------------
	// hint var
	bool isHinting = false;
	Vector3 endBlockPos = new Vector3 (0, 0, 0);
	Block startBlock = null, endBlock = null;
	int numHint = 0;
	Vector2 startBlockXY = new Vector2 (0, 0), endBlockXY = new Vector2 (0, 0);
	//------
	void CreateHintUndo ()
	{
		hintUndo = new UndoModule ();
		for (int i = 0; i < listAllBlock.Count; i++) {
			Block bl = listAllBlock [i];
			hintUndo.Values [bl.x, bl.y] = bl.colorId;
		}
	}

	IEnumerator HintCoroutine (int _hintCount)
	{
		isHinting = true;
		WaitForSeconds wfs = new WaitForSeconds (0.1f);
		int lastNumHint = -1;
		numHint = 0;
		while (numHint < 2) {
			if (lastNumHint != numHint) {
				lastNumHint = numHint;

				if (_hintCount + numHint >= md.steps.Count) {
					hintDot.transform.DOKill ();
					hintDot.transform.position = new Vector3 (20, 20, 0);
					isHinting = false;
					yield break;
				}
				HintStepModule hintStep = md.steps [_hintCount + numHint];

				switch (hintStep.direction) {
				case "up": 
					startBlock = GetBlock (5 + hintStep.column, 11);
					endBlock = GetBlock (5 + hintStep.column, 11 - hintStep.positions);
					break;
				case "down": 
					startBlock = GetBlock (5 + hintStep.column, 6);
					endBlock = GetBlock (5 + hintStep.column, 6 + hintStep.positions);
					break;
				case "right": 
					startBlock = GetBlock (6, 5 + hintStep.row);
					endBlock = GetBlock (6 + hintStep.positions, 5 + hintStep.row);
					break;
				case "left": 
					startBlock = GetBlock (11, 5 + hintStep.row);
					endBlock = GetBlock (11 - hintStep.positions, 5 + hintStep.row);
					break;
				}

				if (startBlock != null && endBlock != null) {
					startBlockXY = new Vector2 (startBlock.x, startBlock.y);
					endBlockXY = new Vector2 (endBlock.x, endBlock.y);
					endBlockPos = endBlock.transform.position;
					hintDot.transform.DOKill ();
					hintDot.transform.position = startBlock.transform.position;
					hintDot.transform.DOMove (endBlock.transform.position, 1F, false).SetLoops (-1, LoopType.Restart);
				}
			}
			/*
			float distance = Vector3.Distance (startBlock.transform.position, endBlockPos);
			Debug.Log ("Distance = " + distance);
			if (distance <= 0.1F) {
				yield return null;
				numHint++;
				CreateHintUndo ();
				hintCount++;
			}
			*/
			yield return wfs;


		}
		hintDot.transform.DOKill ();
		hintDot.transform.position = new Vector3 (20, 20, 0);
		isHinting = false;
	}

	public void Pause ()
	{
		
	}

}

public enum MoveDir
{
	H,
	V
}

[System.Serializable]
public class StageModule
{
	public int color1, color2;
	public List<int> solution, start;
	public List<HintStepModule> steps;
}

[System.Serializable]
public class HintStepModule
{
	public 	string direction;
	public int positions, row, column;

}

[System.Serializable]
public class UndoModule
{
	public UndoModule ()
	{
		Values = new int[18, 18];
	}

	public int[,] Values;
}